#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
This is a simple web service server

"""

import sys, os, subprocess,time, commands
import argparse
import select

sys.path.append(".")
import super_parser,crawler

from bottle import route, run,template,get, post, request,static_file,response
import bottle
import socket
#add lock support to synchronize OpenCV server access
from threading import Lock

OpenCV_mutex=Lock()

reload(sys) 
sys.setdefaultencoding('utf-8')
    
url_prefix = r'http://54.241.13.111:8080/static/images/'

myApiKey = r'pvezh6ggtf6rfyk2ha7gbnvh'
myStoreDir = r'./temp'
myDB=r'./temp.db'
    

@get('/login') # or @route('/login')
def login_form():
    return '''<form method="POST" action="/login">
                <input name="name"     type="text" />
                <input name="password" type="password" />
                <input type="submit" />
              </form>'''

@post('/login') # or @route('/login', method='POST')
def login_submit():
    name     = request.forms.get('name')
    password = request.forms.get('password')
    if check_login(name, password):
        return "<p>Your login was correct</p>"
    else:
        return "<p>Login failed</p>"

def check_login(name, password):
    return True

#image url
@route('/static/images/<filename>')
def server_static(filename):
    return static_file(filename, root='./static/images')

#@route('/static/<filepath:path>')
#def server_static(filepath):
    #return static_file(filepath, root='/home/james/Dropbox/MSS_Work/530/image_search/SuperEngine/static/images/test.jpg')

@route('/my_ip')
def show_ip():
    ip = request.environ.get('REMOTE_ADDR')
    # or ip = request.get('REMOTE_ADDR')
    # or ip = request['REMOTE_ADDR']
    return "Your IP is: %s" % ip


#file upload
@route('/')
@get('/upload') # or @route('/login')
def upload_form():
    upload_form = """<form action="/upload" method="post" enctype="multipart/form-data">
		      Upload an image: <input type="file" name="data" />
		      <input type="submit" name="submit" />
		     </form>"""
    return upload_form
    

@route('/upload', method='POST')
def do_upload():
    #name = request.forms.name
    data = request.files.data
    
    if data and data.file:
        raw = data.file.read() # This is dangerous for big files
        t_stamp = timestamp()
        filename = t_stamp + "_"+ data.filename
        with open(r'./static/images/'+filename,'wb') as open_file:
            open_file.write(raw)
        #return static_file(filename, root='./static/images')
        #my_dict = search_image(url_prefix,filename,3)
        my_dict = {"image_file": filename}
        return my_dict    
    else:
        return "Image upload failed!"


#http://ec2-184-169-228-174.us-west-1.compute.amazonaws.com:8080/static/images/dress_images.jpg

def search_image(url_prefix=None, image_file=None,delay_time=3):
    image_url = url_prefix + image_file
    
    resp_html = "./static/resp_html/"+image_file+".html"
    print "Delay time is : " + str(delay_time)
    print "output html is: " + resp_html
    
    print "Search Image url: " + image_url
    guess_name = "unknown"
    
    # try multiple times to increase the hit rate
    for iterator in range(1,3):
	print "The %d round search ..." %iterator
	ret = super_parser.get_search_resp_html(url=image_url,out_html=resp_html,wait=delay_time)
	if ret == 0:
	    guess_name = super_parser.extract_match_name_for_html(html_str=None,html_file=resp_html)
	    if guess_name is not "unknown":	    
		break;	
	else:
	    print "search failed!"
    print "!!! Best guess for this image: " + guess_name
    #test_id = test_id +1
    return {"source":"public", "guessName" :guess_name}


#search?image_file=my_image_file_name&mode=1_2_3&location=my_location
@route('/search')
def do_image_search_by_arguments():
    image_fn = request.query.image_file
    category = request.query.category
    mode = request.query.mode
    search_location=request.query.location
    my_dict = { }
    #search from public web and return image name
    if mode == "1":
        my_dict = search_image(url_prefix,image_fn,3)
    #search from local image database and return price info
    #TODO: James, Will. add error handling here
    # matching failed, product id doesn't exist
    elif mode == "2":
        #here we can OpenCV service, assume we get a matched image file
        try:
            guess_name = search_local(image_file=image_fn,category=category)
        except:
	    print "OpenCV server execption!"
	    guess_name="fail"
	print "local matched image file: ", guess_name
	if guess_name != "fail":
	    #matched in local images, then to find product id        
	    product_id = crawler.get_product_id_from_image(db=myDB,image_file=guess_name)
	    #product_id != "unknown"
	    if product_id != "unknown":
		json_data = crawler.retrive_product_info(product_id)
		my_dict = json_data
	    else:
		err_msg = "image matched but product is not found in local db"
		my_dict = {"Source":"local","error":err_msg}
	#if no matched image found
	else:
	    my_dict = {"Source":"local","error":"no matched image in local cache"}
    else:
        my_dict = {"Search mode": " is not supported"}
    return my_dict


#generate a uniqe timestamp 
def timestamp():
    now = time.time()
    localtime = time.localtime(now)
    milliseconds = '%03d' % int((now - int(now)) * 1000)
    return time.strftime('%Y%m%d%H%M%S', localtime) + milliseconds

#search local image and price database
# This is a hook point to talk with OpenCV image matching service
def search_local(image_file=None,category="camera"):
    #call OpenCV app to do local matching
    #add a mutex/lock here to synchronize access
    try:
	#get the lock first
	OpenCV_mutex.acquire()
	host = socket.gethostname() # Get local machine name
	port = 5000                # Reserve a port for your service.
	s = socket.socket()
	s.settimeout(120)
	s.connect((host, port))
	image_file = "../static/images/" + image_file
	print "local search with file name " + image_file
	msg = image_file +"," + category.lower() + "\0" #raw_input('CLIENT >> ')
	s.send(msg)
	msg = 'fail'
	
	s.setblocking(0)
	ready = select.select([s], [], [], 120)
	if ready[0]:
	    msg = s.recv(1024)
	    #print 'SERVER >> ', msg
	    msg = msg.strip()
	s.close()
    finally:
	#release the lock whatever in any condition
	OpenCV_mutex.release()
    return msg

    

### to using paste multithread web server
#application = bottle.default_app()
#from paste import httpserver
#httpserver.serve(application, host='0.0.0.0', port=8080)

### to use gunicorn multithread web server
app = bottle.default_app()

# main function to test the module

#def main(argv=None):
    #if argv is None:
      #argv = sys.argv
    #print argv
    
    #reload(sys) 
    #sys.setdefaultencoding('utf-8')
    
 

#if __name__ == "__main__":
    #sys.exit(main())  
